package com.dz.risk.controller;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.dz.risk.common.ResponseVO;
import com.dz.risk.common.enums.ReportFormsTypeEnum;
import com.dz.risk.common.exception.RRException;
import com.dz.risk.common.utils.DateUtils;
import com.dz.risk.common.utils.ZyStringUtils;
import com.dz.risk.pojo.domain.ReportFormsEntity;
import com.dz.risk.pojo.model.InportFormulaModel;
import com.dz.risk.pojo.model.PageModel;
import com.dz.risk.service.ReportFormsDataValueService;
import com.dz.risk.service.ReportFormsService;
import com.dz.risk.service.RiskFactorValueService;
import com.dz.risk.validation.Add;
import com.dz.risk.validation.Update;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

/**
 * 报表管理Api
 *
 * @author Doke
 * @date 2021/7/26 10:08
 */
@Api(tags = "报表基本信息Api")
@RestController
@RequestMapping("/dz-ftsp/stest/reportForms")
public class ReportFormsController {

    private final ReportFormsService reportFormsService;

    private final ReportFormsDataValueService reportFormsDataValueService;

    private final RiskFactorValueService riskFactorValueService;

    @Autowired
    public ReportFormsController(ReportFormsService reportFormsService, ReportFormsDataValueService reportFormsDataValueService, RiskFactorValueService riskFactorValueService) {
        this.reportFormsService = reportFormsService;
        this.reportFormsDataValueService = reportFormsDataValueService;
        this.riskFactorValueService = riskFactorValueService;
    }

    @ApiOperation("根据参数查询报表结构树")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "当前页(默认 : 1)", dataType = "Integer"),
            @ApiImplicitParam(name = "rows", value = "显示条数(默认 : 10)", dataType = "Integer"),
            @ApiImplicitParam(name = "reportFormsName", value = "报表名称", dataType = "String"),
            @ApiImplicitParam(name = "reportFormsSerialNumber", value = "报表编号", dataType = "String"),
    })
    @GetMapping("/selectReportFormsTreeByParams")
    public ResponseVO selectReportFormsTreeByParams(PageModel pageModel, String reportFormsSerialNumber, String reportFormsName) {
        return ResponseVO.ok(reportFormsService.selectReportFormsTreeByParams(pageModel, reportFormsName, reportFormsSerialNumber));
    }

    @ApiOperation("查询所有报表基本信息(无版本得原始报表信息)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "reportFormsName", value = "报表名称", dataType = "String"),
            @ApiImplicitParam(name = "reportFormsSerialNumber", value = "报表编号", dataType = "String")
    })
    @GetMapping("/selectBasicInformationByParams")
    public ResponseVO selectBasicInformationByParams(String reportFormsSerialNumber, String reportFormsName) {
        return ResponseVO.ok(reportFormsService.selectBasicInformationByParams(reportFormsSerialNumber, reportFormsName));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "reportFormsSerialNumber", value = "报表编号", dataType = "String")
    })
    @ApiOperation("根据报表编号删除报表基本信息以及下属所有报表")
    @GetMapping("/deleteByReportFormsSerialNumber")
    public ResponseVO deleteByReportFormsSerialNumber(@RequestParam("reportFormsSerialNumber") String reportFormsSerialNumber) {
        reportFormsService.deleteByReportFormsSerialNumber(reportFormsSerialNumber);
        return ResponseVO.ok();
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "beginDate", value = "报表开始时间 : yyyy-MM-dd", required = true, dataType = "String"),
            @ApiImplicitParam(name = "endDate", value = "报表结束时间 : yyyy-MM-dd", required = true, dataType = "String"),
            @ApiImplicitParam(name = "reportFormsName", value = "报表名称", dataType = "String"),
            @ApiImplicitParam(name = "reportType", value = "报表类型", dataType = "ReportFormsTypeEnum")
    })
    @ApiOperation("查询报表版本开始结束时间等于参数开始结束时间的报表信息集合")
    @GetMapping("/selectReportFormsByBeginDateAndEndDate")
    public ResponseVO selectReportFormsByBeginDateAndEndDate(@RequestParam("beginDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date beginDate,
                                                             @RequestParam("endDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
                                                             String reportFormsName, ReportFormsTypeEnum reportType) {
        return ResponseVO.ok(reportFormsService.selectReportFormsByBeginDateAndEndDate(beginDate, endDate, reportType, reportFormsName));
    }

    @ApiOperation("根据旧报表模板信息生成新版本报表模板信息")
    @PostMapping("/generateNewVersionReportFormsByReportFormsId")
    public ResponseVO generateNewVersionReportFormsByReportFormsId(@RequestBody @Validated(ReportFormsEntity.GenerateNewVersionReportForms.class) ReportFormsEntity reportFormsEntity) {
        reportFormsService.generateNewVersionReportFormsByReportFormsId(reportFormsEntity);
        return ResponseVO.ok();
    }

    /**
     * 新增 - 报表基本信息
     *
     * @param reportFormsEntity
     * @return
     */
    @ApiOperation("新增报表基本信息")
    @PostMapping("/add")
    public ResponseVO add(@RequestBody @Validated({Add.class}) ReportFormsEntity reportFormsEntity) {
        ResponseVO formsEntity = reportFormsService.queryOnly(reportFormsEntity);
        if (formsEntity != null) {
            return formsEntity;
        }
        reportFormsService.save(reportFormsEntity);
        return ResponseVO.ok();
    }

    /**
     * 修改 - 报表基本信息updateDynamicExcelById
     *
     * @param reportFormsEntity
     * @return
     */
    @ApiOperation("根据违约债券Id更新信息 ")
    @PostMapping("/update")
    public ResponseVO update(@RequestBody @Validated({Update.class}) ReportFormsEntity reportFormsEntity) {
        ResponseVO formsEntity = reportFormsService.queryOnly(reportFormsEntity);
        if (formsEntity != null) {
            return formsEntity;
        }
        reportFormsService.update(reportFormsEntity);
        return ResponseVO.ok();
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "calculatingTime", value = "计算时间 : yyyy-MM-dd HH:mm:ss", required = true, dataType = "Date"),
            @ApiImplicitParam(name = "reportFormsIds", value = "报表ID集合(ID之间用逗隔开)", required = true, dataType = "String"),
    })
    @ApiOperation("报表模板数据计算")
    @GetMapping("/reportFormsTemplateDataCalculate")
    public ResponseVO reportFormsTemplateDataCalculate(@RequestParam("calculatingTime") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date calculatingTime,
                                                       @RequestParam("reportFormsIds") String reportFormsIds) throws InterruptedException, TimeoutException, BrokenBarrierException, ExecutionException {
        reportFormsService.reportFormsTemplateDataCalculate(calculatingTime, ZyStringUtils.splitToList(reportFormsIds));
        return ResponseVO.ok();
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "calculatingTime", value = "计算时间 : yyyy-MM-dd HH:mm:ss", required = true, dataType = "Date"),
            @ApiImplicitParam(name = "beginDate", value = "报表开始时间 : yyyy-MM-dd", required = true, dataType = "String"),
            @ApiImplicitParam(name = "endDate", value = "报表结束时间 : yyyy-MM-dd", required = true, dataType = "String"),
            @ApiImplicitParam(name = "threadFlag", value = "0: 不设置阈值, 1:设置 ", required = true, dataType = "Integer")
    })
    @ApiOperation("根据版本批量计算报表")
    @GetMapping("/reportFormsCalculateBatchByVersion")
    public ResponseVO reportFormsCalculateBatchByVersion(@RequestParam("beginDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date beginDate,
                                                         @RequestParam("endDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
                                                         @RequestParam("calculatingTime") @DateTimeFormat(pattern = "yyyy-MM-dd") Date calculatingTime,
                                                         @RequestParam("threadFlag")  Integer threadFlag
    ) throws InterruptedException, TimeoutException, BrokenBarrierException, ExecutionException {
        if(threadFlag == 1){
            riskFactorValueService.updateThreadFlag(DateUtils.dateToStringMonth(calculatingTime));
        }
        reportFormsService.reportFormsCalculateBatchByVersion(beginDate, endDate, calculatingTime);
        return ResponseVO.ok();
    }


    /**
     * 导入公式
     */
    @ApiOperation("导入报表公式")
    @PostMapping("/inport")
    public ResponseVO inport(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request) throws Exception {
        ImportParams params = new ImportParams();
        params.setHeadRows(1);
        // params.setTitleRows(0);
        List<InportFormulaModel> result = ExcelImportUtil.importExcel(multipartFile.getInputStream(),
                InportFormulaModel.class, params);
        for (int i = 0; i < result.size(); i++) {
            InportFormulaModel inportFormulaModel = result.get(i);
            if (inportFormulaModel.getFormulaId() == null) {
                int num = i+1;
                return new ResponseVO(100, "第"+num+"行，公式编号不能为空或公式编号不能存在中文");
            }
        }
        try {
            reportFormsDataValueService.setUpTheFormula(result, request);
        } catch (RRException e) {
            e.printStackTrace();
            return new ResponseVO(e.getCode(), e.getMessage());
        }
        return ResponseVO.ok("设置成功");
    }

    /**
     * 导入临时表数据
     */
    @ApiOperation("导出报表公式模板")
    @GetMapping("/doExport")
    public void doExport(HttpServletResponse response) throws IOException {
        SXSSFWorkbook wb = new SXSSFWorkbook();
        Sheet sh = wb.createSheet();
        //公式编号	公式详细	字段	备注
        String[] titles = {"公式编号", "公式详细", "字段", "备注"};
        Row row = sh.createRow(0);
        CellStyle style = wb.createCellStyle();
        style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);
        style.setAlignment(HorizontalAlignment.CENTER);

        // 第一行设置标题
        for (int i = 0; i < titles.length; i++) {
            String title = titles[i];
            Cell cell1 = row.createCell(i);
            cell1.setCellValue(title);
            cell1.setCellStyle(style);
        }

        sh.setColumnWidth(0, 6000);
        sh.setColumnWidth(1, 6000);
        String fileName = "中间表数据.xlsx";
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        wb.write(response.getOutputStream());
        wb.close();
    }
}
